import datetime

class Bill:
    def __init__(self, date, amount, category, remark):
        self.date = date
        self.amount = amount
        self.category = category
        self.remark = remark

    def __str__(self):
        return f"{self.date} | {self.category} | {self.amount} | {self.remark}"


class Budget:
    def __init__(self, limit):
        self.limit = limit
        self.spent = 0

    def add_spent(self, amount):
        self.spent += amount

    def remaining_budget(self):
        return self.limit - self.spent


class FinancialSystem:
    def __init__(self):
        self.incomes = []
        self.expenses = []
        self.budget = None

    def record_income(self):
        date = input("请输入收入日期 (YYYY-MM-DD): ")
        amount = self._get_positive_float("请输入收入金额: ")
        category = input("请输入收入类别: ")
        remark = input("请输入备注: ")

        self.incomes.append(Bill(date, amount, category, remark))
        print("收入记录成功！")

    def record_expense(self):
        date = input("请输入支出日期 (YYYY-MM-DD): ")
        amount = self._get_positive_float("请输入支出金额: ")
        category = input("请输入支出类别: ")
        remark = input("请输入备注: ")

        self.expenses.append(Bill(date, amount, category, remark))

        if self.budget:
            self.budget.add_spent(amount)

        print("支出记录成功！")

    def show_all_bills(self):
        print("\n--- 收入记录 ---")
        for income in self.incomes:
            print(income)

        print("\n--- 支出记录 ---")
        for expense in self.expenses:
            print(expense)

    def query_bills(self):
        query_type = input("选择查询类型: 1. 按日期 2. 按日期范围 3. 按类别\n请输入选择: ")

        if query_type == '1':
            date = input("请输入查询日期 (YYYY-MM-DD): ")
            self._query_by_date(date)
        elif query_type == '2':
            start_date = input("请输入开始日期 (YYYY-MM-DD): ")
            end_date = input("请输入结束日期 (YYYY-MM-DD): ")
            self._query_by_date_range(start_date, end_date)
        elif query_type == '3':
            category = input("请输入查询类别: ")
            self._query_by_category(category)
        else:
            print("无效的选择!")

    def _query_by_date(self, date):
        print(f"查询日期: {date}")
        print("\n--- 收入记录 ---")
        for income in self.incomes:
            if income.date == date:
                print(income)

        print("\n--- 支出记录 ---")
        for expense in self.expenses:
            if expense.date == date:
                print(expense)

    def _query_by_date_range(self, start_date, end_date):
        start = datetime.datetime.strptime(start_date, "%Y-%m-%d")
        end = datetime.datetime.strptime(end_date, "%Y-%m-%d")
        print(f"查询日期范围: {start_date} 到 {end_date}")

        print("\n--- 收入记录 ---")
        for income in self.incomes:
            income_date = datetime.datetime.strptime(income.date, "%Y-%m-%d")
            if start <= income_date <= end:
                print(income)

        print("\n--- 支出记录 ---")
        for expense in self.expenses:
            expense_date = datetime.datetime.strptime(expense.date, "%Y-%m-%d")
            if start <= expense_date <= end:
                print(expense)

    def _query_by_category(self, category):
        print(f"查询类别: {category}")
        print("\n--- 收入记录 ---")
        for income in self.incomes:
            if income.category == category:
                print(income)

        print("\n--- 支出记录 ---")
        for expense in self.expenses:
            if expense.category == category:
                print(expense)

    def set_budget(self):#添加预算
        limit = self._get_positive_float("请输入月度预算金额: ")
        self.budget = Budget(limit)
        print(f"预算设置成功，月度预算为 {limit} 元")

    def show_budget_status(self):#月度统计
        if self.budget:
            remaining = self.budget.remaining_budget()
            print(f"当前剩余预算: {remaining} 元")
        else:
            print("尚未设置预算！")

    def monthly_statistics(self):
        income_total = sum([income.amount for income in self.incomes])
        expense_total = sum([expense.amount for expense in self.expenses])

        print(f"本月总收入: {income_total} 元")
        print(f"本月总支出: {expense_total} 元")
        print(f"本月净收入: {income_total - expense_total} 元")

        print("\n各类别支出统计:")
        categories = {}
        for expense in self.expenses:
            if expense.category not in categories:
                categories[expense.category] = 0
            categories[expense.category] += expense.amount

        for category, total in categories.items():
            print(f"{category}: {total} 元")

    def _get_positive_float(self, prompt):
        while True:
            try:
                value = float(input(prompt))
                if value <= 0:
                    print("金额必须为正数，请重新输入！")
                else:
                    return value
            except ValueError:
                print("输入无效，请输入有效的数字！")

    def menu(self):
        while True:
            print("\n--- 个人账单管理系统 ---")
            print("1. 记录收入")
            print("2. 记录支出")
            print("3. 展示所有账单")
            print("4. 查询账单")
            print("5. 设置预算")
            print("6. 查看预算剩余")
            print("7. 月度统计")
            print("8. 退出")
            choice = input("请输入选项: ")

            if choice == '1':
                self.record_income()
            elif choice == '2':
                self.record_expense()
            elif choice == '3':
                self.show_all_bills()
            elif choice == '4':
                self.query_bills()
            elif choice == '5':
                self.set_budget()
            elif choice == '6':
                self.show_budget_status()
            elif choice == '7':
                self.monthly_statistics()
            elif choice == '8':
                print("感谢使用个人账单管理系统！")
                break
            else:
                print("无效的选项，请重新选择。")


if __name__ == "__main__":
    system = FinancialSystem()
    system.menu()
